import prettier, { Plugin } from "prettier";
const root = "https://cdn.jsdelivr.net/npm/prettier/esm/";
const plugins = {
    javascript: ["babel"],
    typescript: ["typescript"],
    typescriptreact: ["typescript", "html"],
    vue: ["html", "typescript", "babel", "postcss"],
    "vue-postcss": ["html", "typescript", "babel", "postcss"],
    "vue-html": ["html", "typescript", "babel", "postcss"],
    "vue-sugarss": ["html", "typescript", "babel", "postcss"],
    css: ["postcss"],
    scss: ["postcss"],
    less: ["postcss"],
    html: ["html"],
    json: ["json"],
    jsonc: ["json"],
    markdown: ["markdown"],
    yaml: ["yaml"],
    javascriptreact: ["babel", "html"],
};
const pluginCache = new Map<string, Plugin<any>>();
type AccessLanguageId = keyof typeof plugins;
export const loadPlugin = (pluginName: string) => {
    if (pluginCache.has(pluginName)) return;
    return import(root + "parser-" + pluginName + ".mjs").then((res) => {
        pluginCache.set(pluginName, res.default);
        return res.default;
    });
};
const getPlugin = (id: AccessLanguageId) => {
    return Promise.all(
        (plugins[id] || []).map(async (i) => {
            const p = pluginCache.get(i)!;
            if (!p) {
                const pl = await loadPlugin(i);
                return pl;
            }

            return p;
        })
    );
};
import { TextDocument, TextEdit, Range, languages } from "vscode";
import { Extension } from "../ExtensionManager";

export const Prettier: Extension = () => {
    let init = false;
    return {
        name: "prettier",
        setup() {
            if (init) return;
            init = true;
            const bar = this.statusBar.addStatus("prettier");
            bar.classList.add("codicon");
            bar.textContent = " Prettier";
            bar.title = "Prettier Record";

            const langs = Object.keys(plugins);
            langs.forEach((id) => {
                languages.registerDocumentFormattingEditProvider(
                    { language: id },
                    {
                        async provideDocumentFormattingEdits(
                            doc: TextDocument
                        ) {
                            bar.textContent = "Formatting";
                            const plugins = await getPlugin(
                                id as AccessLanguageId
                            );
                            const result = prettier.format(doc.getText(), {
                                filepath: doc.fileName,

                                plugins,
                            });
                            if (!result) {
                                // No edits happened, return never so VS Code can try other formatters
                                return [];
                            }
                            bar.textContent = id;
                            return [minimalEdit(doc, result)];
                        },
                    }
                );
            });
        },
    };
};

const minimalEdit = (document: TextDocument, string1: string) => {
    const string0 = document.getText();
    // length of common prefix
    let i = 0;
    while (
        i < string0.length &&
        i < string1.length &&
        string0[i] === string1[i]
    ) {
        ++i;
    }
    // length of common suffix
    let j = 0;
    while (
        i + j < string0.length &&
        i + j < string1.length &&
        string0[string0.length - j - 1] === string1[string1.length - j - 1]
    ) {
        ++j;
    }
    const newText = string1.substring(i, string1.length - j);
    const pos0 = document.positionAt(i);
    const pos1 = document.positionAt(string0.length - j);

    return TextEdit.replace(new Range(pos0, pos1), newText);
};
